#include <iostream>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <time.h>

#include "img.h"

//https://xantorohara.github.io/led-matrix-editor/

#define ROTATE 0

//将图像的xy轴交换得到新编码, 这样就可以使用左右移位来移动图像。
uint64_t image_rotate(uint64_t image)
{
    uint8_t hex2[8];
    uint64_t image_swaped = 0;
    //U64有8个hex2:  00-ff
    for (int h=0;h<8; h++) {
        hex2[h] = (image >> h*8) & 0xff;//get row
        for (int bit=0; bit<8; bit++) {
            uint64_t bitx = (hex2[h]>>bit) & 1;//LSB
            // image_swaped |= bitx<<((7-bit)*8+(h));//向左旋转
            image_swaped |= bitx<<((bit)*8+(7-h));//向右旋转
        }
    }
    return image_swaped;
}

uint64_t image_rotate_left(uint64_t image)
{
    uint8_t hex2[8];
    uint64_t image_swaped = 0;
    //U64有8个hex2:  00-ff
    for (int h=0;h<8; h++) {
        hex2[h] = (image >> h*8) & 0xff;//get row
        for (int bit=0; bit<8; bit++) {
            uint64_t bitx = (hex2[h]>>bit) & 1;//LSB
            image_swaped |= bitx<<((7-bit)*8+(h));//向左旋转
            // image_swaped |= bitx<<((bit)*8+(7-h));//向右旋转
        }
    }
    return image_swaped;
}

// static void image_decode(uint64_t image, uint8_t *out_buffer88)
// {
//     //从下往上
//     for (int i = 0; i < 8; i++)
//     {
//         uint8_t row = (image >> i * 8) & 0xFF;
//         for (int j = 0; j < 8; j++)
//         {
//             out_buffer88[i * 8 + j] = (row >> j) & 1;
//         }
//     }
// }

uint8_t gram[8*8];
//需要左转90
void displayImage(uint64_t image)
{
    #if 1
    // image = swap_coordinate(image);
    #endif
    //从下往上
    for (int i = 0; i < 8; i++)
    {
        uint8_t row = (image >> i * 8) & 0xFF;
        for (int j = 0; j < 8; j++)
        {
            #if ROTATE
            gram[j*8+(7-i)] = (row >> j) & 1;
            #else
            gram[i*8+j] = (row >> j) & 1;
            #endif
        }
    }
}


void show_char_pc()
{
    system("cls");
    printf("---------------\n");
    for (int i = 0; i < 8; ++i)
    {
        for (int j = 0; j < 8; ++j)
        {
            // printf("%c ", gram[(7-j)*8+(i)] ? 'x' : ' ');
            printf("%c ", gram[i*8+j] ? 'x' : ' ');
        }
        printf("\n");
    }
    printf("---------------\n");
}

void display_ascii(char ch)
{
    // Check if character is valid
    if (ch < 32 || ch > 126)
        return;
    uint64_t ascii_img = ascii_8x8[ch - 32];
    displayImage(ascii_img);
    show_char_pc();
}

uint64_t hex2u64(const char* hex) {
    uint64_t ret = 0;
    uint64_t n_power = 1;
    if (strlen(hex) >= 16) {
        for (int i=0; i<16; i++) {
            char c = hex[15-i];
            if ( c >= 'a' && c <= 'f') {
                ret += (c - 'a' + 10) * n_power;
            }
            else if ( c >= 'A' && c <= 'F') {
                ret += (c - 'A' + 10) * n_power;
            }
            else if ( c >= '0' && c <= '9') {
                ret += (c - '0') * n_power;
            }

            n_power *= 16;
        }
    }
    return ret;
}

//0 = 完全左边。 8 = 完全右边
uint64_t combine2(uint64_t left, uint64_t right, int move)
{
    uint64_t img = left >> (move * 8);
    uint64_t right_part_low = right & (0x100<<(move*8))-1;
    //move 0 = 0xff
    //move 1 = 0xffff
    //move 2 = 0xffffff
    img |= right_part_low << ((7-move)*8);
    return img; 
}

uint64_t combine(uint64_t left, uint64_t right, int move)
{
    uint8_t left8[16];
    uint8_t right8[8];
    uint64_t comb64;
    memcpy(left8, &left, sizeof(uint64_t));
    memcpy(left8+8, &right, sizeof(uint64_t));
    memcpy(right8, &right, sizeof(uint64_t));
    uint8_t comb8[8];
    //l0 l1 l2 l3 l4 l5 l6 l7 r0 r1 r2 r3 r4 r5 r6 r7
    //r0 r1 r2 r3 r4 r5 r6 r7
    //
    memcpy(&comb64, left8+move, 8);
    // memcpy()

}


void show_string_roll(const char *str)
{
    uint8_t len = strlen(str);
    uint64_t renderer_image;
    //往左滚动
    uint64_t  current_char_image, next_char_image;
    if (len == 1) {
        //show ascii
        return ;
    }
    for (int i=0;i<len-1; i++) {
        current_char_image = ascii_8x8[str[i] - ' '];
        if (i <= len-1) {
            next_char_image = ascii_8x8[str[i+1] - ' '];
        }
        else {
            // next_char_image = 0;
        }
        current_char_image = image_rotate(current_char_image);
        next_char_image = image_rotate(next_char_image);
        
        for (int col=0;col<8; col++) {
            renderer_image = combine(current_char_image,
                next_char_image, col);

            renderer_image = image_rotate_left(renderer_image);//only for pc.
            displayImage(renderer_image);
            show_char_pc();
            Sleep(100);
        }
    }
}

#include "template.hpp"
#include <iostream>
using namespace std;

void song(const char* name = "o my papa", int times = 1)
{
    cout<<name<<endl;
}

struct box{
    // char marker[40];
    const char* marker;
    float height;
    float width;
    float length;
    float volume;
};

void show_box(const struct box& b)
{
    cout << b.marker << endl;
    cout << b.height << endl;
    cout << b.width << endl;
    cout << b.length <<endl;
}

void show2_calc_volume(struct box& b)
{
    b.volume = b.height * b.width * b.length;
    cout << b.volume <<endl;
}

struct box b1 = 
{
    .marker = "marker",
    .height = 10,
    .width = 20,
    .length = 30,
};


int main(int, char **)
{
    show_box(b1);
    show2_calc_volume(b1);
    song();
    int langgo = 100;
    int rabbit = 200;
    myswap(langgo, rabbit);
    cout << "langgo:" << langgo <<endl;
    cout << "rabbit:" << rabbit <<endl;

    // std::cout << "Hello, world!\n";
    // for (int i=' '; i<'~'; i++)
        // display_ascii(i);
    // display_ascii('A');
    // uint64_t image2 = swap_coordinate(0xf00f);
    // uint64_t expect = 0x4040404080808080;
    // printf("%llx\n", image2);
    // printf("test %s\n", image2==expect?"pass":"fail");

    // show_string_roll("12345");
    // const char* u64hex =  "183c7effffff6600";
    // const uint64_t u64 = 0x183c7effffff6600;
    // if (hex2u64(u64hex) == u64) {
    //     std::cout << "test pass!\n";
    // }
    // else {
    //     std::cout << "test failed!\n";
    // }
    // for (int i = 0; i < 10; i++)
    // {
    //     displayImage(IMAGES[i]);
    //     show_char_pc();
    // }
}
